

package big

import (
	"fmt"
	"io"
	"strings"
)

var floatZero Float

func (z *Float) SetString(s string) (*Float, bool) {
	if f, _, err := z.Parse(s, 0); err == nil {
		return f, true
	}
	return nil, false
}

func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
	prec := z.prec
	if prec == 0 {
		prec = 64
	}

	z.form = zero

	z.neg, err = scanSign(r)
	if err != nil {
		return
	}

	z.mant, b, fcount, err = z.mant.scan(r, base, true)
	if err != nil {
		return
	}

	var exp int64
	var ebase int
	exp, ebase, err = scanExponent(r, true, base == 0)
	if err != nil {
		return
	}

	if len(z.mant) == 0 {
		z.prec = prec
		z.acc = Exact
		z.form = zero
		f = z
		return
	}


	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
	exp5 := int64(0)

	if fcount < 0 {
		d := int64(fcount)
		switch b {
		case 10:
			exp5 = d
		case 2:
			exp2 += d
		case 8:
		case 16:
		default:
			panic("unexpected mantissa base")
		}
	}

	switch ebase {
	case 10:
		exp5 += exp
	case 2:
		exp2 += exp
	default:
		panic("unexpected exponent base")
	}

	if MinExp <= exp2 && exp2 <= MaxExp {
		z.prec = prec
		z.form = finite
		z.exp = int32(exp2)
		f = z
	} else {
		err = fmt.Errorf("exponent overflow")
		return
	}

	if exp5 == 0 {
		z.round(0)
		return
	}

	if exp5 < 0 {
		z.Quo(z, p.pow5(uint64(-exp5)))
	} else {
		z.Mul(z, p.pow5(uint64(exp5)))
	}

	return
}

var pow5tab = [...]uint64{
	1,
	5,
	25,
	125,
	625,
	3125,
	15625,
	78125,
	390625,
	1953125,
	9765625,
	48828125,
	244140625,
	1220703125,
	6103515625,
	30517578125,
	152587890625,
	762939453125,
	3814697265625,
	19073486328125,
	95367431640625,
	476837158203125,
	2384185791015625,
	11920928955078125,
	59604644775390625,
	298023223876953125,
	1490116119384765625,
	7450580596923828125,
}

func (z *Float) pow5(n uint64) *Float {
	const m = uint64(len(pow5tab) - 1)
	if n <= m {
		return z.SetUint64(pow5tab[n])
	}

	z.SetUint64(pow5tab[m])
	n -= m

	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)

	for n > 0 {
		if n&1 != 0 {
			z.Mul(z, f)
		}
		f.Mul(f, f)
		n >>= 1
	}

	return z
}

// 浮点=（尾数|前缀pmantissa）[指数]。
// prefix=“0”[“b”|“b”|“b”|“o”|“o”|“x”]。
// 尾数=位数。“[位数]|位数|”位数。
// pmantissa=[“”]位“[digits]|[“”]位|”位。
// 指数=（“e”|“e”|“p”|“p”）[符号]位数。
// 位=位{[“”]位}。
// digit=“0”。。。“9”|“a”。。。“z”|“A”。。。“Z”。
// 
// 基参数必须为0、2、8、10或16。提供无效的基本
// 参数将导致运行时死机。
// 
// 对于基数0，数字前缀决定实际基数：
// /`0b'或`0b'的前缀选择基数2，`0o'或`0o'选择基数8，
// /`0x'或`0x'选择基数16。否则，实际基数为10，
// 不接受前缀。不支持八进制前缀“0”（前导
// /“0”仅被视为“0”）。
// 
// “p”或“p”指数表示以2为基数（而不是以10为基数）的指数；
// 例如，“0x1.fffffffffff p1023”（使用基数0）表示
// 最大浮点64值。对于十六进制尾数，指数字符
// 必须是“p”或“p”中的一个，如果存在的话（不能将“e”或“e”指数指示符
// 与尾数数字区分开来）。
// 
// 返回的*Float f为零，z值有效，但在报告错误时未定义。
// 
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
	// 扫描无法处理±Inf 
	if len(s) == 3 && (s == "Inf" || s == "inf") {
		f = z.SetInf(false)
		return
	}
	if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
		f = z.SetInf(s[0] == '-')
		return
	}

	r := strings.NewReader(s)
	if f, b, err = z.scan(r, base); err != nil {
		return
	}

	// 整个字符串必须已被使用
	if ch, err2 := r.ReadByte(); err2 == nil {
		err = fmt.Errorf("expected end of string, found %q", ch)
	} else if err2 != io.EOF {
		err = err2
	}

	return
}

// ParseFloat类似于f.Parse（s，base），f设置为给定精度
// 和舍入模式。
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
	return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}

var _ fmt.Scanner = (*Float)(nil) // *浮点必须实现fmt.Scanner 

// /扫描是fmt.Scanner的一个支持例程；它将z设置为
// 扫描号码的值。它接受其谓词受
// fmt支持的格式。扫描浮点值，这些浮点值是：
// 'b'（二进制）、'e'、'e'、'f'、'g'和'g'。
// 扫描无法处理±Inf。
func (z *Float) Scan(s fmt.ScanState, ch rune) error {
	s.SkipSpace()
	_, _, err := z.scan(byteReader{s}, 0)
	return err
}
